import { Vector3 } from 'three-legacy';

import {
  CMEVENTS,
  EventsRes,
  KEYBOARD_KEY,
  MouseInfo,
  MouseStyle,
  PickerState,
  preventKeys,
  STATE,
  Types,
} from '@amcax/base';
import { Picker3D, PickerAssembly, PickerMgr } from '@amcax/renderer';
import { BaseEventCenter } from '@app-cad/common/events/BaseEventCenter';
import { ctx2, userEvents } from '@app-cad/module';

import { measureRenderManager } from '@app-base/manager/MeasureRenderManager';
import { COMMON_EVENTS } from '../Constants';
import { BsplineEditor } from '../utils';

export enum PICKTYPE {
  MODEL = 1, // 体
  FACE = 2, // 面
  LINE = 3, // 线
  POINT = 4, // 点
  ALL = 6,
}

export const pickSetting = {
  1: { model: true },
  2: { face: true },
  3: { line: true },
  4: { point: true },
  6: { all: true },
};

let editingGroup: boolean; //编辑组

/* 事件模块 */
export class EventCenter3D extends BaseEventCenter {
  pickType: PICKTYPE = PICKTYPE.ALL; // 拾取类型（线、面、体）
  clickTimerCount = 0;
  clickTimer: NodeJS.Timeout;
  idsMap: Map<number, number>;

  constructor(
    public picker: Picker3D | PickerAssembly = PickerMgr.getPicker<Picker3D>(
      '3d',
    ),
  ) {
    super();
  }

  getEventRes<T extends MouseEvent | PointerEvent | KeyboardEvent>(
    event: T,
    eventName: string,
  ): EventsRes<T> {
    return {
      ...super.getEventRes(event, eventName),
      idsMap: this.idsMap,
    };
  }

  // 设置拾取类型
  setPickType(type: number) {
    if (this.pickType !== type) {
      this.pickType = type;
      this.picker.clickNull();
      userEvents.emit(COMMON_EVENTS.CLICK_NULL);
      this.picker.setGlobalPickType(type);
    }
    return this;
  }

  setState(state: string) {
    if (state === this.state) {
      return this;
    }

    if (state != STATE.DEFAULT) {
      this.picker.setState(PickerState.onCommand);
    }
    this.touchExit();
    this.state = state;
    if (state === 'editGroup') {
      editingGroup = true;
    }
    return this;
  }

  setDefault(force: boolean = false) {
    this.picker.setState(PickerState.default);
    if (force) {
      this.state = STATE.DEFAULT;
      editingGroup = false;
    } else {
      if (editingGroup) {
        this.state = 'editGroup';
      } else {
        this.state = STATE.DEFAULT;
      }
    }
    this.clearExit();
    return this;
  }

  onCanvasPointerDown(ev: EventsRes<MouseEvent>): void {
    this.picker.setPointerDownPos(ev);
  }

  // 默认状态下支持多选和单击空白处清空
  // 鼠标左键和右键都可以选中模型，点击右键选中的模型后可显示上下文菜单(上下文菜单的逻辑见：@app-cad/components/ContextMenu)
  onCanvasPointerup(ev: EventsRes<PointerEvent>) {
    const { event, button } = ev;

    if (this.state === STATE.DEFAULT && (button.onLeft || button.onRight)) {
      const measureSelectResult = measureRenderManager.selectByButton(button);
      if (measureSelectResult) {
        this.picker.clearSelectedModel();
      }

      if (measureSelectResult == null && this.idsMap && this.idsMap.size > 0) {
        this.picker.select(event);
        // 默认状态下支持洞口十字定位
        const modelData = this.picker.getCurrentModel() as any;
        if (
          modelData &&
          (modelData.objInfo?.type === Types.HOLE ||
            modelData.objInfo?.type === 'opening') &&
          modelData.objInfo.parent != undefined
        ) {
          this.pickedHoleId = modelData.idInfo.o;
        } else {
          if (this.pickedHoleId) {
            this.picker.uncheckModels([this.pickedHoleId]);
            const children = modelData?.objInfo?.child;
            if (children) {
              for (let i = 0, l = children.length; i < l; i++) {
                if (children[i] === this.pickedHoleId) {
                  this.picker.selectModels([modelData.idInfo.o]);
                }
              }
            }
          }
          this.pickedHoleId = null;
        }

        // 曲线编辑
        const pickedLine = this.picker.getCurrentEdge() as any;
        if (pickedLine && pickedLine?.objInfo?.type === 'Part::Bspline') {
          // 进入曲线编辑状态
          const dxid = pickedLine.idInfo?.o;
          const pointsArray = pickedLine.objInfo?.params?.points;
          if (!pointsArray) {
            this.idsMap = null;
            return;
          }
          const keyPoints: Array<Vector3> = [];
          for (let i = 0, l = pointsArray?.length; i < l; i++) {
            const point = new Vector3().fromArray(pointsArray[i]);
            keyPoints.push(point);
          }
          // 曲线编辑
          BsplineEditor().start(dxid, keyPoints);
        }
      } else {
        // 鼠标右键不取消选中模型
        if (!button.onRight) {
          this.picker.clickNull();
          userEvents.emit(COMMON_EVENTS.CLICK_NULL);
        }
      }
      this.picker.marqueePointerUp();

      // 显示右键菜单
      if (button.onRight) {
        userEvents.emit(CMEVENTS.MODEL_RIGHT_CLICK, event);
      }
    }

    this.idsMap = null;
  }

  onKeyUp(ev: EventsRes<KeyboardEvent>): void {
    const { event } = ev;
    if (preventKeys.indexOf(event.key) != -1) {
      event.preventDefault();
    }

    // 快捷撤销
    if (
      (event.key === KEYBOARD_KEY.KEY_Z ||
        event.key === KEYBOARD_KEY.KEY_UPPERCASE_Z) &&
      event.ctrlKey === true
    ) {
      userEvents.emit(CMEVENTS.CMD_UNDO, event);
    }

    // 快捷重做
    if (
      (event.key === KEYBOARD_KEY.KEY_Y ||
        event.key === KEYBOARD_KEY.KEY_UPPERCASE_Y) &&
      event.ctrlKey === true
    ) {
      userEvents.emit(CMEVENTS.CMD_REDO, event);
    }

    // if (
    //   event.key === KEYBOARD_KEY.DELETE ||
    //   event.key === KEYBOARD_KEY.BACKSPACE
    // ) {
    //   if (this.state === STATE.DEFAULT && event.target == document.body) {
    //     deleteModels()
    //   }
    // }
    // deleteModels()
  }

  onCanvasPointerMove(ev: EventsRes<MouseEvent>) {
    const { button } = ev;

    // 拾取
    if (this.pickingData.pixelBuffer && !button.buttonDown) {
      this.idsMap = this.mouseMoving(this.mouse);
    }

    // 默认状态下支持选择体
    if (this.state === STATE.DEFAULT && !button.buttonDown) {
      MouseStyle.setName('');
      if (measureRenderManager.pick(ev) == null) {
        const pickSet = pickSetting[this.pickType];
        this.picker.pick(ev, pickSet);
      } else {
        this.picker.clearHovers();
        ctx2.viewer.requestRender();
      }
    }
    // 框选功能
    if (
      this.state === STATE.DEFAULT &&
      button.onLeft &&
      this.pickType === PICKTYPE.MODEL
    ) {
      this.picker.marqueeSelection(ev);
    }

    return ev;
  }

  mouseMoving(mouse: MouseInfo) {
    const mouseX = mouse.x;
    const mouseY = mouse.y;
    const idMap = new Map();
    const setId = (id: number) => {
      if (!idMap.has(id)) {
        idMap.set(id, 1);
      } else {
        const t = idMap.get(id);
        idMap.set(id, t + 1);
      }
    };
    for (let x = mouseX - 2; x < mouseX + 2; x++) {
      for (let y = mouseY - 2; y < mouseY + 2; y++) {
        const i =
          Math.round(
            x + (this.canvas.clientHeight - y) * this.canvas.clientWidth,
          ) * 4; // 获取像素点index
        const id =
          (this.pickingData.pixelBuffer[i] << 16) |
          (this.pickingData.pixelBuffer[i + 1] << 8) |
          this.pickingData.pixelBuffer[i + 2];
        if (id != 0) {
          setId(id);
        }
      }
    }
    return idMap.size > 0 ? idMap : null;
  }

  offCanvasPointerUp(event: PointerEvent): void {
    if (event.target === this.sceneSetup.domElement().childNodes[1]) {
      return;
    }
    if (document.activeElement.tagName !== 'INPUT') {
      event.preventDefault();
    }
    event.stopPropagation();
    // 结束框选;
    this.picker.marqueePointerUp();
    return;
  }
}
